import paho.mqtt.client as mqtt
import json
import time
from django.db import close_old_connections
from app01.models import VibrationData, BearingHealth, VibrationAudio
from .base import BaseService


class MQTTService(BaseService):
    def __init__(self):
        super().__init__()
        self.client = None
        self.is_connected = False
        self.retry_interval = 10  # 重连接间隔
        self.bearing_id = 0     # 若要修改bearing_id， 必须先终止进程，否则mqtt线程不会停止
        self.config = {
            "broker": "broker.emqx.io",
            "port": 1883,
            "topic": "ESP32C3/data_send",
            "qos": 1
        }

    def _run(self):
        while True:
            try:
                if not self.is_connected:
                    print(f"尝试连接MQTT代理 ({self.config['broker']}:{self.config['port']})...")
                    self.client = mqtt.Client()
                    self.client.on_connect = self._on_connect
                    self.client.on_message = self._on_message
                    self.client.connect(self.config["broker"], self.config["port"], 60)
                    self.client.loop_start()
                time.sleep(self.retry_interval)
            except Exception as e:
                print(f"连接异常：{str(e)}")
                time.sleep(self.retry_interval)

    def _on_connect(self, client, userdata, flags, rc):
        if rc == 0:
            print("MQTT 连接成功")
            self.is_connected = True
            client.subscribe(self.config["topic"], qos=self.config["qos"])
        else:
            print(f"MQTT 连接失败，错误码：{rc}")
            self.is_connected = False

    def _on_message(self, client, userdata, msg):
        # print(f"当前bearing_id: {self.bearing_id}")  # 调试日志
        close_old_connections()
        try:
            payload = json.loads(msg.payload.decode())
            data = payload.get('Data', {})

            # 获取加速度和速度数据
            x_acc = data.get('x_acc_rms', 0)
            y_acc = data.get('y_acc_rms', 0)
            z_acc = data.get('z_acc_rms', 0)
            x_vel = data.get('x_v_rms', 0)
            y_vel = data.get('y_v_rms', 0)
            z_vel = data.get('z_v_rms', 0)

            # 验证加速度和速度数据
            acc_threshold = 15  # 加速度阈值
            vel_threshold = 10  # 速度阈值

            # 检查是否有任一加速度超过阈值
            if any(abs(acc) > acc_threshold for acc in [x_acc, y_acc, z_acc]):
                print(f"加速度数据超过阈值({acc_threshold})，跳过存储: x={x_acc}, y={y_acc}, z={z_acc}")
                return

            # 检查是否有任一速度超过阈值
            if any(abs(vel) > vel_threshold for vel in [x_vel, y_vel, z_vel]):
                print(f"速度数据超过阈值({vel_threshold})，跳过存储: x={x_vel}, y={y_vel}, z={z_vel}")
                return

            # 创建振动数据记录
            vibration_data = VibrationData.objects.create(
                x_acc_rms=x_acc,
                y_acc_rms=y_acc,
                z_acc_rms=z_acc,
                x_v_rms=x_vel,
                y_v_rms=y_vel,
                z_v_rms=z_vel,
                temperature=data.get('temperature', 0),
                bearing_id=self.bearing_id
            )

            # 音频数据处理
            if 'AudioData' in data:
                audio_samples = data['AudioData']
                # 验证音频数据格式
                if isinstance(audio_samples, list) and len(audio_samples) == 128:
                    VibrationAudio.objects.create(
                        vibration_data=vibration_data,
                        audio_samples=audio_samples,
                        bearing_id=self.bearing_id
                        # sample_rate 使用模型默认值
                    )
                else:
                    print(
                        f"音频数据格式无效：长度={len(audio_samples) if isinstance(audio_samples, list) else '非列表'}")

            # 执行健康分析
            self._analyze_bearing_health(vibration_data)
            print(f"存储成功：{vibration_data.id}")
        except Exception as e:
            print(f"数据处理错误：{str(e)}")
        finally:
            close_old_connections()

    def _analyze_bearing_health(self, vibration_data):
        try:
            BearingHealth.objects.create(
                vibration_data=vibration_data,
                overall_status='normal',
                confidence_level=0.85,
                bearing_id=self.bearing_id
            )
        except Exception as e:
            print(f"健康分析失败：{str(e)}")


# 单例模式初始化
mqtt_client = MQTTService()
